#include <QtGui/QDoubleSpinBox>
#include "DecoratedDoublePropertyManager.h"

/**************** DecoratedDoublePropertyManager ******************/
DecoratedDoublePropertyManager::DecoratedDoublePropertyManager(QObject *parent)
: QtDoublePropertyManager(parent)
{
}

DecoratedDoublePropertyManager::~DecoratedDoublePropertyManager()
{
}

QString DecoratedDoublePropertyManager::prefix(const QtProperty *property) const
{
	if (!propertyToData.contains(property))
		return QString();
	return propertyToData[property].prefix;
}

QString DecoratedDoublePropertyManager::suffix(const QtProperty *property) const
{
	if (!propertyToData.contains(property))
		return QString();
	return propertyToData[property].suffix;
}

void DecoratedDoublePropertyManager::setPrefix(QtProperty *property, const QString &prefix)
{
	if (!propertyToData.contains(property))
		return;

	DecoratedDoublePropertyManager::Data data = propertyToData[property];
	if (data.prefix == prefix)
		return;

	data.prefix = prefix;
	propertyToData[property] = data;

	emit propertyChanged(property);
	emit prefixChanged(property, prefix);
}

void DecoratedDoublePropertyManager::setSuffix(QtProperty *property, const QString &suffix)
{
	if (!propertyToData.contains(property))
		return;

	DecoratedDoublePropertyManager::Data data = propertyToData[property];
	if (data.suffix == suffix)
		return;

	data.suffix = suffix;
	propertyToData[property] = data;

	emit propertyChanged(property);
	emit suffixChanged(property, suffix);
}

QString DecoratedDoublePropertyManager::valueText(const QtProperty *property) const
{
	QString text = QtDoublePropertyManager::valueText(property);
	if (!propertyToData.contains(property))
		return text;

	DecoratedDoublePropertyManager::Data data = propertyToData[property];
	text = data.prefix + text + data.suffix;

	return text;
}

void DecoratedDoublePropertyManager::initializeProperty(QtProperty *property)
{
	propertyToData[property] = DecoratedDoublePropertyManager::Data();
	QtDoublePropertyManager::initializeProperty(property);
}

void DecoratedDoublePropertyManager::uninitializeProperty(QtProperty *property)
{
	propertyToData.remove(property);
	QtDoublePropertyManager::uninitializeProperty(property);
}


/**************** DecoratedDoubleSpinBoxFactory ******************/
DecoratedDoubleSpinBoxFactory::DecoratedDoubleSpinBoxFactory(QObject *parent)
: QtAbstractEditorFactory<DecoratedDoublePropertyManager>(parent)
{
	originalFactory = new QtDoubleSpinBoxFactory(this);
}

DecoratedDoubleSpinBoxFactory::~DecoratedDoubleSpinBoxFactory()
{
	// not need to delete editors because they will be deleted by originalFactory in its destructor
}

void DecoratedDoubleSpinBoxFactory::connectPropertyManager(DecoratedDoublePropertyManager *manager)
{
	originalFactory->addPropertyManager(manager);
	connect(manager, SIGNAL(prefixChanged(QtProperty *, const QString &)), this, SLOT(slotPrefixChanged(QtProperty *, const QString &)));
	connect(manager, SIGNAL(suffixChanged(QtProperty *, const QString &)), this, SLOT(slotSuffixChanged(QtProperty *, const QString &)));
}

QWidget *DecoratedDoubleSpinBoxFactory::createEditor(DecoratedDoublePropertyManager *manager, QtProperty *property,
													 QWidget *parent)
{
	QtAbstractEditorFactoryBase *base = originalFactory;
	QWidget *w = base->createEditor(property, parent);
	if (!w)
		return 0;

	QDoubleSpinBox *spinBox = qobject_cast<QDoubleSpinBox *>(w);
	if (!spinBox)
		return 0;

	spinBox->setPrefix(manager->prefix(property));
	spinBox->setSuffix(manager->suffix(property));

	createdEditors[property].append(spinBox);
	editorToProperty[spinBox] = property;

	return spinBox;
}

void DecoratedDoubleSpinBoxFactory::disconnectPropertyManager(DecoratedDoublePropertyManager *manager)
{
	originalFactory->removePropertyManager(manager);
	disconnect(manager, SIGNAL(prefixChanged(QtProperty *, const QString &)), this, SLOT(slotPrefixChanged(QtProperty *, const QString &)));
	disconnect(manager, SIGNAL(suffixChanged(QtProperty *, const QString &)), this, SLOT(slotSuffixChanged(QtProperty *, const QString &)));
}

void DecoratedDoubleSpinBoxFactory::slotPrefixChanged(QtProperty *property, const QString &prefix)
{
	if (!createdEditors.contains(property))
		return;

	DecoratedDoublePropertyManager *manager = propertyManager(property);
	if (!manager)
		return;

	QList<QDoubleSpinBox *> editors = createdEditors[property];
	QListIterator<QDoubleSpinBox *> itEditor(editors);
	while (itEditor.hasNext()) {
		QDoubleSpinBox *editor = itEditor.next();
		editor->setPrefix(prefix);
	}
}

void DecoratedDoubleSpinBoxFactory::slotSuffixChanged(QtProperty *property, const QString &prefix)
{
	if (!createdEditors.contains(property))
		return;

	DecoratedDoublePropertyManager *manager = propertyManager(property);
	if (!manager)
		return;

	QList<QDoubleSpinBox *> editors = createdEditors[property];
	QListIterator<QDoubleSpinBox *> itEditor(editors);
	while (itEditor.hasNext()) {
		QDoubleSpinBox *editor = itEditor.next();
		editor->setSuffix(prefix);
	}
}

void DecoratedDoubleSpinBoxFactory::slotEditorDestroyed(QObject *object)
{
	QMap<QDoubleSpinBox *, QtProperty *>::ConstIterator itEditor =
		editorToProperty.constBegin();
	while (itEditor != editorToProperty.constEnd()) {
		if (itEditor.key() == object) {
			QDoubleSpinBox *editor = itEditor.key();
			QtProperty *property = itEditor.value();
			editorToProperty.remove(editor);
			createdEditors[property].removeAll(editor);
			if (createdEditors[property].isEmpty())
				createdEditors.remove(property);
			return;
		}
		itEditor++;
	}
}